package geektime.spring.springbucks.service;

import geektime.spring.springbucks.mapper.CoffeeOrderMapper;
import geektime.spring.springbucks.model.Coffee;
import geektime.spring.springbucks.model.CoffeeOrder;
import geektime.spring.springbucks.model.OrderState;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static javax.transaction.Transactional.TxType.NOT_SUPPORTED;

@Slf4j
@Service
@Transactional
@CacheConfig(cacheNames = "coffeeOrder")
public class CoffeeOrderService {

    @Autowired
    private CoffeeOrderMapper coffeeOrderMapper;

    @CacheEvict(allEntries = true)
    public CoffeeOrder createOrder(String customer, Coffee...coffee) {
        CoffeeOrder order = CoffeeOrder.builder()
                .customer(customer)
                .items(new ArrayList<>(Arrays.asList(coffee)))
                .state(OrderState.INIT)
                .build();
        coffeeOrderMapper.saveOrder(order);
        coffeeOrderMapper.saveCoffeeOrder(order);
        log.info("New Order: {}", order);
        return order;
    }

    @CacheEvict(allEntries = true)
    public boolean updateState(CoffeeOrder order, OrderState state) {
        if (state.compareTo(order.getState()) <= 0) {
            log.warn("Wrong State order: {}, {}", state, order.getState());
            return false;
        }
        order.setState(state);
        coffeeOrderMapper.update(order);
        log.info("Updated Order: {}", order);
        return true;
    }

    @Cacheable
    @Transactional(NOT_SUPPORTED)
    public CoffeeOrder findById(Long id) {
        CoffeeOrder coffeeOrder = coffeeOrderMapper.findById(id);
        log.info("find Order: {}", coffeeOrder);
        return coffeeOrder;
    }

    @Cacheable
    @Transactional(NOT_SUPPORTED)
    public List<CoffeeOrder> findAll() {
        List<CoffeeOrder> coffeeOrders = coffeeOrderMapper.findAll();
        coffeeOrders.forEach(c -> log.info("find all: {}", c));
        return coffeeOrders;
    }

    @CacheEvict(allEntries = true)
    public void reloadOrder() {
    }
}
